home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Telnet / NCSA / tn3270 2.3d26 source / SPPC / driver.c next >
Text File  |  1991-05-28  |  11KB  |  505 lines

  1. #if !defined(USEDUMP)
  2.     #include "drvlib.h"
  3. #else
  4.     #pragma load "drvDumpFile"
  5. #endif
  6.  
  7. #include "sppcinterface.h"
  8.  
  9. #define MSGNUM        24        /* number of outstanding messages allowed */
  10. #define CLIENTNUM    8        /* number of simultaneous clients */
  11. #define NAMELENGTH    32        /* significant chars. in client name */
  12. #define MSGLENGTH    128        /* maximum length of message */
  13.  
  14. typedef struct {
  15.     unsigned char name[NAMELENGTH+1];
  16.     unsigned char inuse;
  17.     short refnum;
  18.     } clientrec;
  19.     
  20. typedef struct {
  21.     unsigned char data[MSGLENGTH];
  22.     unsigned long id;
  23.     unsigned long replyid;
  24.     short datalen;
  25.     short torefnum;
  26.     short fromrefnum;
  27.     unsigned char inuse;
  28.     } msgrec;
  29.  
  30. struct drvGlobals {
  31.     short refcounter;                /* last refnum given out */
  32.     unsigned long msgcounter;        /* last msg id given out */
  33.     clientrec clist[CLIENTNUM];        /* client data */
  34.     msgrec mlist[MSGNUM];            /* message data */
  35.     };
  36.  
  37. /* subroutine prototypes */
  38. OSErr doregister(struct drvGlobals**, unsigned char*, short*);
  39. OSErr doderegister(struct drvGlobals**, short);
  40. OSErr dolookup(struct drvGlobals**, unsigned char*, short*);
  41. OSErr dosend(struct drvGlobals**, short, unsigned long,
  42.             short, Handle, unsigned short, unsigned long*);
  43. OSErr doget(struct drvGlobals**, short, unsigned long, short *,
  44.             Handle, unsigned short*, unsigned long*, unsigned long *);
  45. OSErr doclear(struct drvGlobals**, short);
  46. OSErr dodelmsg(struct drvGlobals**, unsigned long*);
  47. short lookupname(clientrec*, unsigned char *);
  48. short lookupref(clientrec*, short);
  49. void msgclear(msgrec*, short);
  50.  
  51. pascal OSErr DRVROpen(CntrlParam *ctlPB, DCtlPtr dCtl)
  52. {
  53. #pragma unused (ctlPB)
  54. THz hz;
  55.  
  56. if (dCtl->dCtlStorage != 0) {    /* return if already open */
  57.     return(noErr);
  58.     }
  59.  
  60. hz = GetZone();                    /* allocate storage for globals */
  61. SetZone(SystemZone());
  62. dCtl->dCtlStorage = NewHandle((Size)sizeof(struct drvGlobals));
  63. SetZone(hz);
  64. if (dCtl->dCtlStorage == 0) {
  65.     return(mFulErr);
  66.     }
  67. else {                            /* clear storage and return */
  68.     memset(*(dCtl->dCtlStorage), 0, sizeof(struct drvGlobals)); 
  69.     return(noErr);
  70.     }
  71. }
  72.  
  73. pascal OSErr DRVRClose(CntrlParam *ctlPB, DCtlPtr dCtl)
  74. {
  75. #pragma unused (ctlPB)
  76.  
  77. if (dCtl->dCtlStorage == 0) {    /* return if not open */
  78.     return(notOpenErr);
  79.     }
  80.                                 /* dispose of global storage */
  81. DisposHandle(dCtl->dCtlStorage);
  82. return(noErr);
  83. }
  84.  
  85. pascal OSErr DRVRControl(CntrlParam *ctlPB, DCtlPtr dCtl)
  86. {
  87. parmrec * pmr;
  88. struct drvGlobals** ghandle;
  89. OSErr rc;
  90.  
  91. /* get parameter structure pointer from csParam array */
  92. memcpy(&pmr, ctlPB->csParam, 4);
  93.  
  94. ghandle = (struct drvGlobals**)(dCtl->dCtlStorage);
  95. if (ghandle == 0) {
  96.     return(notOpenErr);
  97.     }
  98. HLock((Handle)ghandle);
  99.  
  100. switch(ctlPB->csCode) {
  101.     case SPPCreg:
  102.                     rc = doregister(ghandle, pmr->name, pmr->refptr);                    
  103.                     break;
  104.     case SPPCdereg:
  105.                     rc = doderegister(ghandle, pmr->refnum);
  106.                     break;
  107.     case SPPClookup:
  108.                     rc = dolookup(ghandle, pmr->name, pmr->refptr);
  109.                     break;
  110.     case SPPCsend:
  111.                     rc = dosend(ghandle, pmr->refnum, pmr->replyid, 
  112.                                 pmr->refnum2, pmr->msg, pmr->msglen,
  113.                                 pmr->msgid);
  114.                     break;
  115.     case SPPCget:
  116.                     rc = doget(ghandle, pmr->refnum, pmr->replyid,
  117.                                 pmr->refptr, pmr->msg, pmr->msglenptr,
  118.                                 pmr->msgid, pmr->replyidptr);
  119.                     break;
  120.     case SPPCclear:
  121.                     rc = doclear(ghandle, pmr->refnum);
  122.                     break;
  123.     case SPPCdelmsg:
  124.                     rc = dodelmsg(ghandle, pmr->msgid);
  125.                     break;
  126.     default:
  127.                     rc = paramErr;
  128.                     break;
  129.     }
  130. HUnlock((Handle)ghandle);
  131. return(rc);
  132. }
  133.  
  134. /* The following calls are not implemented by this driver */
  135.  
  136. pascal OSErr DRVRPrime(CntrlParam *ctlPB, DCtlPtr dCtl)
  137. {
  138. #pragma unused (ctlPB, dCtl)
  139. return(unimpErr);
  140. }
  141.  
  142. pascal OSErr DRVRStatus(CntrlParam *ctlPB, DCtlPtr dCtl)
  143. {
  144. #pragma unused (ctlPB, dCtl);
  145. return(unimpErr);
  146. }
  147.  
  148. /* subroutines for control functions */
  149.  
  150. OSErr doregister(struct drvGlobals** gh, unsigned char* cName,
  151.                short* cRefNum)
  152. {
  153. unsigned char newname[NAMELENGTH+1];
  154. short i, slen, match;
  155. clientrec * cp;
  156.  
  157. (*cRefNum) = 0;
  158. slen = strlen(cName);
  159. if (slen == 0) {
  160.     return(bdNamErr);
  161.     }
  162. if (slen > NAMELENGTH) slen = NAMELENGTH;
  163. memset(newname, 0, NAMELENGTH+1);
  164. memcpy(newname, cName, slen);
  165.  
  166. cp = (*gh)->clist;            /* pointer to client array */
  167.  
  168. /* check if name is in use */
  169. match = lookupname(cp, newname);
  170.  
  171. /* if name is in use, return refnum and error code */
  172. if (match >= 0) {
  173.     (*cRefNum) = cp[match].refnum;
  174.     return(dupFNErr);
  175.     }
  176.  
  177. /* find an empty slot for new name */
  178. match = -1;
  179. for (i=0; i < CLIENTNUM; i++) {
  180.     if (cp[i].inuse == 0) {
  181.         match = i;
  182.         break;
  183.         }
  184.     }
  185.  
  186. /* check for no more room */
  187. if (match == -1) {
  188.     return(dirFulErr);
  189.     }
  190.  
  191. /* define new client */
  192. memcpy(cp[match].name, newname, NAMELENGTH+1);
  193. cp[match].inuse = 1;
  194. (*gh)->refcounter++;
  195. cp[match].refnum = (*gh)->refcounter;
  196. (*cRefNum) = cp[match].refnum;
  197. return(noErr);
  198. }
  199.  
  200. OSErr doderegister(struct drvGlobals** gh, short cRefNum)
  201. {
  202. short match;
  203. clientrec * cp;
  204. msgrec * mp;
  205.  
  206. cp = (*gh)->clist;            /* pointer to client array */
  207.  
  208. /* check if refnum is in use */
  209. match = lookupref(cp, cRefNum);
  210.  
  211. /* error if refnum not found */
  212. if (match == -1) {
  213.     return(rfNumErr);
  214.     }
  215.  
  216. /* delete this client */
  217. memset(cp[match].name, 0, NAMELENGTH+1);
  218. cp[match].inuse = 0;
  219. cp[match].refnum = 0;
  220.  
  221. /* also delete any pending messages */
  222. mp = (*gh)->mlist;            /* pointer to message array */
  223. msgclear(mp, cRefNum);
  224.  
  225. return(noErr);
  226. }
  227.  
  228. OSErr dolookup(struct drvGlobals** gh, unsigned char* cName,
  229.              short* cRefNum)
  230. {
  231. unsigned char lkpname[NAMELENGTH+1];
  232. short slen, match;
  233. clientrec * cp;
  234.  
  235. (*cRefNum) = 0;
  236. slen = strlen(cName);
  237. if (slen == 0) {
  238.     return(bdNamErr);
  239.     }
  240. if (slen > NAMELENGTH) slen = NAMELENGTH;
  241. memset(lkpname, 0, NAMELENGTH+1);
  242. memcpy(lkpname, cName, slen);
  243.  
  244. cp = (*gh)->clist;            /* pointer to client array */
  245.  
  246. /* check if name is in use */
  247. match = lookupname(cp, lkpname);
  248.  
  249. /* if name is in use, return refnum and success code */
  250. if (match >= 0) {
  251.     (*cRefNum) = cp[match].refnum;
  252.     return(noErr);
  253.     }
  254.  
  255. /* return not found error */
  256. return(fnfErr);
  257. }
  258.  
  259. OSErr dosend(struct drvGlobals** gh, short cRefNum,
  260.              unsigned long replyId, short toRefNum,
  261.            Handle theMessage, unsigned short msglen,
  262.            unsigned long *msgid)
  263. {
  264. short i, match;
  265. clientrec * cp;
  266. msgrec * mp;
  267. Size hsize;
  268.  
  269. (*msgid) = 0;                /* initialize result */
  270.  
  271. cp = (*gh)->clist;            /* pointer to client array */
  272.  
  273. /* check if source refnum is valid  */
  274. match = lookupref(cp, cRefNum);
  275.  
  276. /* error if source refnum not found */
  277. if (match == -1) {
  278.     return(rfNumErr);
  279.     }
  280.  
  281. /* check if destination refnum is valid  */
  282. match = lookupref(cp, toRefNum);
  283.  
  284. /* error if destination refnum not found */
  285. if (match == -1) {
  286.     return(rfNumErr);
  287.     }
  288.  
  289. /* check message length is valid */
  290. if ((msglen == 0) || (msglen > MSGLENGTH)) {
  291.     return(memSCErr);
  292.     }
  293.  
  294. /* check message handle is valid */
  295. hsize = GetHandleSize(theMessage);
  296. if (hsize < msglen) {
  297.     return(memSCErr);
  298.     }
  299.  
  300. mp = (*gh)->mlist;            /* pointer to message array */
  301.  
  302. /* find an empty slot for new message */
  303. match = -1;
  304. for (i=0; i < MSGNUM; i++) {
  305.     if (mp[i].inuse == 0) {
  306.         match = i;
  307.         break;
  308.         }
  309.     }
  310.  
  311. /* check for no more room */
  312. if (match == -1) {
  313.     return(dirFulErr);
  314.     }
  315.  
  316. /* define new message */
  317. memcpy(mp[match].data, (*theMessage), (size_t)msglen); 
  318. mp[match].datalen = msglen;
  319. mp[match].torefnum = toRefNum;
  320. mp[match].replyid = replyId;
  321. mp[match].fromrefnum = cRefNum;
  322. mp[match].inuse = 1;
  323. (*gh)->msgcounter++;
  324. mp[match].id = (*gh)->msgcounter;
  325. (*msgid) = mp[match].id;
  326. return(noErr);
  327. }
  328.  
  329. OSErr doget(struct drvGlobals** gh, short cRefNum, 
  330.           unsigned long replyId, short* fromRefNum,
  331.           Handle theMessage, unsigned short *msglenptr,
  332.           unsigned long * msgid, unsigned long * replyidptr)
  333. {
  334. short i, match;
  335. clientrec * cp;
  336. msgrec * mp;
  337. Size hsize;
  338.  
  339. cp = (*gh)->clist;            /* pointer to client array */
  340.  
  341. (*fromRefNum) = 0;            /* initialize results */
  342. (*msglenptr) = 0;
  343. (*msgid) = 0;
  344.  
  345. /* check if destination refnum is valid  */
  346. match = lookupref(cp, cRefNum);
  347.  
  348. /* error if destination refnum not found */
  349. if (match == -1) {
  350.     return(rfNumErr);
  351.     }
  352.  
  353. mp = (*gh)->mlist;            /* pointer to message array */
  354.  
  355. /* search for a message for the destination */
  356. /* return the matching message with the lowest message id */
  357. match = -1;
  358. for (i=0; i < MSGNUM; i++) {
  359.     if (mp[i].inuse && (mp[i].torefnum == cRefNum) &&
  360.         ((mp[i].replyid == replyId) || (replyId == 0))) {
  361.         if (match == -1) {
  362.             match = i;
  363.             }
  364.         else {
  365.             if (mp[i].id < mp[match].id) {
  366.                 match = i;
  367.                 }
  368.             }
  369.         }
  370.     }
  371.  
  372. /* check for no message found */
  373. if (match == -1) {
  374.     return(fnfErr);
  375.     }
  376.  
  377. /* return message control data */
  378. (*msglenptr) = mp[match].datalen;
  379. (*fromRefNum) = mp[match].fromrefnum;
  380. (*msgid) = mp[match].id;
  381. (*replyidptr) = mp[match].replyid;
  382.  
  383.  
  384. /* check message handle is valid */
  385. hsize = GetHandleSize(theMessage);
  386. if (hsize < mp[match].datalen) {
  387.     return(memSCErr);
  388.     }
  389.  
  390. /* return the message data */
  391. memcpy(*theMessage, mp[match].data, mp[match].datalen);
  392.  
  393. /* delete this message */
  394. memset(mp[match].data, 0, MSGLENGTH);
  395. mp[match].datalen = mp[match].torefnum = mp[match].fromrefnum = 0;
  396. mp[match].replyid = 0;
  397. mp[match].inuse = 0;
  398. mp[match].id = 0;
  399.  
  400. return(noErr);
  401. }
  402.  
  403. OSErr doclear(struct drvGlobals** gh, short cRefNum)
  404. {
  405. short match;
  406. clientrec * cp;
  407. msgrec * mp;
  408.  
  409. cp = (*gh)->clist;            /* pointer to client array */
  410.  
  411. /* check if refnum is in use */
  412. match = lookupref(cp, cRefNum);
  413.  
  414. /* error if refnum not found */
  415. if (match == -1) {
  416.     return(rfNumErr);
  417.     }
  418.  
  419. /* delete any pending messages */
  420. mp = (*gh)->mlist;            /* pointer to message array */
  421. msgclear(mp, cRefNum);
  422.  
  423. return(noErr);
  424. }
  425.  
  426. OSErr dodelmsg(struct drvGlobals** gh, unsigned long *msgid)
  427. {
  428. short i, match;
  429. msgrec * mp;
  430.  
  431. mp = (*gh)->mlist;            /* pointer to message array */
  432.  
  433. /* look for a matching message */
  434. match = -1;
  435. for (i=0; i < MSGNUM; i++) {
  436.     if (mp[i].id == (*msgid)) {
  437.         match = i;
  438.         break;
  439.         }
  440.     }
  441.  
  442. /* check for message not found */
  443. if (match == -1) {
  444.     return(fnfErr);
  445.     }
  446.  
  447. /* delete this message */
  448. memset(mp[match].data, 0, MSGLENGTH);
  449. mp[match].datalen = mp[match].torefnum = mp[match].fromrefnum = 0;
  450. mp[match].replyid = 0;
  451. mp[match].inuse = 0;
  452. mp[match].id = 0;
  453.  
  454. return(noErr);
  455. }
  456.  
  457. short lookupname(clientrec *cp, unsigned char *name)
  458. {
  459. short i, match;
  460.  
  461. /* Return clist index for name, or -1 */
  462. match = -1;
  463. for (i=0; i < CLIENTNUM; i++) {
  464.     if (cp[i].inuse) {
  465.         if (strcmp(name, cp[i].name) == 0) {
  466.             match = i;
  467.             break;
  468.             }
  469.         }
  470.     }
  471. return(match);
  472. }
  473.  
  474. short lookupref(clientrec *cp, short refnum)
  475. {
  476. short i, match;
  477.  
  478. /* Return clist index for refnum, or -1 */
  479. match = -1;
  480. for (i=0; i < CLIENTNUM; i++) {
  481.     if (cp[i].inuse) {
  482.         if (cp[i].refnum == refnum) {
  483.             match = i;
  484.             break;
  485.             }
  486.         }
  487.     }
  488. return(match);
  489. }
  490.  
  491. void msgclear(msgrec* mp, short toref)
  492. {
  493. short i;
  494.  
  495. /* delete any messages with a matching torefnum */
  496. for (i=0; i < MSGNUM; i++) {
  497.     if (mp[i].torefnum == toref) {
  498.         memset(mp[i].data, 0, MSGLENGTH);
  499.         mp[i].datalen = mp[i].torefnum = mp[i].fromrefnum = 0;
  500.         mp[i].replyid = 0;
  501.         mp[i].inuse = 0;
  502.         mp[i].id = 0;
  503.         }
  504.     }
  505. }